/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bff.designtime.generator.changeconvertor.methodgenerator;

import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bff.designtime.generator.changeconvertor.FSChangeConvertorGenContext;
import com.inspur.edp.bff.designtime.generator.common.GenUtils;
import com.inspur.edp.bff.designtime.generator.udt.UdtInfo;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.changeset.ValueObjModifyChangeDetail;
import com.inspur.edp.cef.entity.i18n.MultiLanguageInfo;
import com.inspur.edp.cef.generator.DotNetToJavaStringHelper;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import java.util.ArrayList;
import java.util.Arrays;
import lombok.var;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

public class ConvertMultiLanguageModifyPropFromVoGenerator extends ClassMethodGenerator {

  private static final String ParamVmElementCode = "vmElementCode";
  private static final String ParamVmValue = "vmValue";
  private static final String ParamBeChange = "beChange";
  private static final String ParamBeValue = "beValue";
  private FSChangeConvertorGenContext changeConvertorContext;

  public ConvertMultiLanguageModifyPropFromVoGenerator(
      FSChangeConvertorGenContext changeConvertorContext) {
    this.changeConvertorContext = changeConvertorContext;
  }


  // region MethodBody
  @Override
  protected Block buildMethodBody() {
    Statement beValueStatement = getBEValueDeclaration();
    SwitchStatement result = getSwitchBlock();
    for (IGspCommonField gspCommonField : changeConvertorContext.getVmObject()
        .getContainElements()) {
      GspViewModelElement item = (GspViewModelElement) gspCommonField;
      if (item.getIsVirtual()) {
        continue;
      }
      if (DotNetToJavaStringHelper.isNullOrEmpty(item.getMapping().getTargetObjId())) {
        throw new RuntimeException(
            "#GspBefError# 字段" + item.getCode() + " 的Mapping字段ID不允许为空#GspBefError#");
      }

      if (item.getMapping().getTargetMetadataId()
          .equals(changeConvertorContext.getVmGeneratorContext()
              .getVm().getMapping().getTargetMetadataId()) == false) {
        continue;
      }

      Object tempVar = changeConvertorContext.getBeObject()
          .findElement(item.getMapping().getTargetObjId());
      GspBizEntityElement entityElement = (GspBizEntityElement) (
          (tempVar instanceof GspBizEntityElement) ? tempVar : null);
      if (entityElement == null) {
        continue;
      }
      addElementMapBlock(item, entityElement, result);
    }
    Block block = ast.newBlock();
    block.statements().add(beValueStatement);
    block.statements().add(result);
    return block;
  }

  // object beValue =null;
  private Statement getBEValueDeclaration() {
    VariableDeclarationFragment frag = ast.newVariableDeclarationFragment();
    frag.setName(ast.newSimpleName(ParamBeValue));
    frag.setInitializer(ast.newNullLiteral());
    VariableDeclarationStatement statement = ast.newVariableDeclarationStatement(frag);
    statement.setType(ast.newSimpleType(ast.newSimpleName("Object")));
    return statement;
  }

  private SwitchStatement getSwitchBlock() {
    SwitchStatement statement = ast.newSwitchStatement();
    statement.setExpression(ast.newSimpleName(ParamVmElementCode));
    return statement;
  }

  // region AddElementMapBlock
  private void addElementMapBlock(GspViewModelElement vmElement, GspBizEntityElement beElement,
      SwitchStatement result) {
    if (vmElement.getIsUdt()) {
      return;
    }
    switch (vmElement.getObjectType()) {
      case None:
        if (vmElement.getIsUdt() || !vmElement.getIsMultiLanguage() || !vmElement
            .isEnableMultiLanguageInput()) {
          return;
        }
        this.addMultilanguageElementValue(vmElement.getLabelID(), beElement.getLabelID(),
            result);
        return;
      case DynamicProp:
        break;
      case Association:
      case Enum:
        break;
      default:
        throw new RuntimeException(
            "#GspBefError# 错误的类型" + vmElement.getObjectType().toString() + " #GspBefError# ");
    }
  }

  private ExpressionStatement addChange(String change, String key, String valueName,
      boolean isKeyPro) {

    MethodInvocation changeInvocation = ExpressionUtils
        .getMethodInvocation(ast, change, "getPropertyChanges");
    MethodInvocation invocation = ExpressionUtils.getMethodInvocation(ast, changeInvocation, "put");

    Expression keyArgument;
    if (isKeyPro) {
      keyArgument = ast.newSimpleName(key);
    } else {
      StringLiteral literal = ast.newStringLiteral();
      literal.setLiteralValue(key);
      keyArgument = literal;
    }

    invocation.arguments().add(keyArgument);
    invocation.arguments().add(ast.newSimpleName(valueName));

    return ast.newExpressionStatement(invocation);
  }

  // case "beLabelId" + MultiLanguageInfo.MULTILANGUAGETOKEN:
  private void addMultilanguageElementValue(String caseElementLabelId,
      String targetElementLabelId, SwitchStatement result) {
    var caseStatement = ast.newSwitchCase();
    var caseExpression = ast.newStringLiteral();
    caseExpression.setLiteralValue(caseElementLabelId);
    caseStatement.setExpression(caseExpression);
    result.statements().add(caseStatement);
    result.statements().add(
        getMutiLanguageInfoMethod(ParamBeChange, targetElementLabelId, ParamVmValue));
    result.statements().add(ast.newBreakStatement());

    addImport(MultiLanguageInfo.class.getTypeName());
  }

  //this.setVmChangeMultiLanguageInfo(vmChange, "voLabelId", beValue);
  private ExpressionStatement getMutiLanguageInfoMethod(String voChangeDetailPara,
      String elementLabelId, String beValuePara) {
    SuperMethodInvocation methodInvocation = ast.newSuperMethodInvocation();
    methodInvocation.setName(ast.newSimpleName("setChangeDetailMultiLanguageInfo"));
    methodInvocation.arguments().add(ast.newSimpleName(voChangeDetailPara));
    StringLiteral stringLiteral = ast.newStringLiteral();
    stringLiteral.setLiteralValue(elementLabelId);
    methodInvocation.arguments().add(stringLiteral);
    methodInvocation.arguments().add(ast.newSimpleName(beValuePara));
    return ast.newExpressionStatement(methodInvocation);
  }

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
    return new ArrayList<Modifier.ModifierKeyword>(Arrays.asList(
        new Modifier.ModifierKeyword[]{Modifier.ModifierKeyword.PROTECTED_KEYWORD}));
  }

  @Override
  protected boolean getIsOverride() {
    return true;
  }

  @Override
  protected String getMethodName() {
    return "convertMultiLanguageModifyPropFromVo";
  }

  @Override
  protected ArrayList<ParameterInfo> getParameterCollection() {
    ParameterInfo paramEleCode = new ParameterInfo();
    paramEleCode.setParamType(new TypeInfo(String.class));
    paramEleCode.setParamName(ParamVmElementCode);
    ParameterInfo paramValue = new ParameterInfo();
    paramValue.setParamType(new TypeInfo(Object.class));
    paramValue.setParamName(ParamVmValue);
    ParameterInfo paramBeChange = new ParameterInfo();
    paramBeChange.setParamType(new TypeInfo(ModifyChangeDetail.class));
    paramBeChange.setParamName(ParamBeChange);
    return new ArrayList<ParameterInfo>(
        Arrays.asList(new ParameterInfo[]{paramEleCode, paramValue, paramBeChange}));
  }

  @Override
  protected TypeInfo getReturnType() {
    return new TypeInfo("void");
  }
}
